import wrappy from './wrappy'

export const proto = _once(function() {
  Object.defineProperty(Function.prototype, 'once', {
    value: function() {
      return _once(this)
    },
    configurable: true
  })

  Object.defineProperty(Function.prototype, 'onceStrict', {
    value: function() {
      return onceStrict(this)
    },
    configurable: true
  })
})

function _once(fn) {
  const f = function() {
    if(f.called) return f.value
    f.called = true
    return f.value = fn.apply(this, arguments)
  }
  f.called = false
  return f
}

function _onceStrict(fn) {
  const f = function() {
    if(f.called)
      throw new Error(f.onceError)
    f.called = true
    return f.value = fn.apply(this, arguments)
  }
  const name = fn.name || 'Function wrapped with `once`'
  f.onceError = name + ' shouldn\'t be called more than once'
  f.called = false
  return f
}

export const once = wrappy(_once)
export const onceStrict = wrappy(_onceStrict)
